<?php

namespace app\model;

use sheng_pay\SPay;
use think\facade\Cache;
use think\helper\Str;
use think\Model;
use think\model\relation\BelongsTo;

class StationOrder extends Model
{
    public function createOrder()
    {
        $user = request()->user;
        $param = request()->post();
        //获取油站信息
        $station = app(StationBasic::class)->where('state', 1)->where('id', $param['station_id'])->find();
        if (empty($station)) throw new \Exception("没有可用的油站！");
        //获取油站油品信息
        $oil = app(StationOil::class)->where('oil_name', $param['oil'])->where('station_id', $station['id'])->find();
        if (empty($oil)) throw new \Exception("没有可用的油品！");
        $oil = $oil->toArray();
        if (!in_array($param['gun'], $oil['guns'])) throw new \Exception("没有可用的加油枪！");
        //1.计算优惠加油金额
        $prices = ["sat_price", "mon_price", "tue_price", "wed_price", "thu_price", "fri_price", "sat_price"][date("w")];
        $dis_price = $station[$prices] > 0 ? $station[$prices] : $station['default_price'];
        $discount = mathDiscount($station['rate_ unit'], $dis_price, $oil['gun_price']);//优惠金额
        //计算加油数量
        $litter = mathLitter($param['money'], $station['litter_type'], $oil['gun_price']);
        //计算本次优惠后的金额
        $money = $discount != $oil['gun_price'] ? round($litter * $discount, 2) : $param['money'];
        //计算结算金额
        $sett_money = mathSettMoney($litter, $param['money'], $station['settlement_type'], $station['settlement_money'], $oil[$prices] > 0 ? $oil[$prices] : $oil['default_price'], $oil['gun_price'], $oil['rate_unit']);
        $pay = new SPay();
        //放重复提交订单，1分钟内重复支付订单优先查询是否有锁定订单，有的话则提交之前锁定的订单
        if (Cache::has('order_lock_' . $param['pay_id'])) {
            //重复提交订单
            $_order = Cache::get('order_lock_' . $param['pay_id']);
            //查询是否已经支付
            $res = $pay->queryOrder($_order);
            if (!in_array(strtoupper($res['status']), ['PAY_FAIL', 'CLOSED', 'PAY_SUCCESS'])) {
                //重复下单提交订单
                $pay = $this->pay($_order, $money, $pay['pay_id'], $station);
                return $pay['create'];
            }
        }
        //小程序过审
        if ($station['mer_id'] > 0) {
            //判断商家余额是否充足
            $merchant = app(Merchant::class)->where('id', $station['mer_id'])->where('balance', '>=', $sett_money)->where('state', 1)->find();
            if (empty($merchant)) throw new \Exception("商家余额不足！");
            //冻结商家余额
            $merchant->dec("balalnce", $sett_money)->inc("disable_balance", $sett_money)->save();
        }
        //创建订单
        $order = [
            "order_sn" => setOrderSn(),
            "uid" => $user->id ?? '',
            'pay_id' => $param['pay_id'],
            'pay_type' => $param['pay_type'],
            'amount' => $param['money'],
            'money' => $money,
            'discount' => bcsub($param['money'], $money, 2),
            'ser_money' => $station['ser_price'] > 0 ? round($param['money'] * bcdiv($station['ser_price'], 100, 4), 2) : 0,
            'litter' => $litter,
            'merchant_money' => $sett_money,
            'station_id' => $station['id'],
            'oil' => $param['oil'],
            'gun' => $param['gun'],
            'supplier' => 0,
            'state' => 0,
            'gun_price' => $oil['gun_price'],
            'gun_discount' => $station[$prices] > 0 ? $station[$prices] : $station['default_price'],
            'gun_unit' => $station['rate_ unit'] == 1 ? '' : '%',
        ];
        Cache::set('order_lock_' . $param['pay_id'], $order['order_sn'], 60);
        $this->save($order);
        //生成支付订单
        $pay = $this->pay($order['order_sn'], $money, $param['pay_id'], $station);
        $this->where('id', $this->id)->save(['payer' => $pay['payInfo'], 'payment_sn' => $pay['create']['transactionId']]);
        return $pay['create'];
    }

    public function pay($order_sn, $amount, $open_id, $station): array
    {
        $pays = [
            "openid" => $open_id,
            "appid" => "wx2eb2e36c4aa4829e"
        ];
        $pay = new SPay();
        $create = $pay->create("wx_jsapi", $order_sn, $amount, "{$station['name']}加油订单", "致胜四方{$station['name']}加油订单", $pays, env("pay_notify") . Str::random(6, 9));
        $payInfo = json_decode($create['payInfo'], true);
        $create['payInfo'] = $payInfo;
        return compact("payInfo", "create");
    }

    public function station(): BelongsTo
    {
        return $this->belongsTo(StationBasic::class, 'station_id');
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'uid');
    }

    public function supplierInfo(): BelongsTo
    {
        return $this->belongsTo(Supplier::class, 'supplier');
    }

    public function lst(): array
    {
        $param = request()->param();
        $station = request()->station ?? [];
        $data = $this->with(['station', 'supplierInfo'])->when(!empty($param['payment_time']), function ($query) use ($param) {
            $query->where('payment_time', 'between', [$param['payment_time'][0] . ' 00:00:00', $param['payment_time'][1] . ' 23:59:59']);
        })->when(!empty($station), function ($query) use ($station) {
            $query->whereIn('station_id', $station['id']);
        })->when(!empty($param['oil']), function ($query) use ($param) {
            $query->where('oil', $param['oil']);
        })->when(!empty($param['supplier']), function ($query) use ($param) {
            $supplier = Supplier::whereLike('name', "%$param[supplier]%")->column("id");
            $query->whereIn('supplier', $supplier);
        })->when(isset($param['order_state']) && $param['order_state'] != '', function ($query) use ($param) {
            $query->where('state', $param['order_state']);
        })->when(!empty($param['search']), function ($query) use ($param) {
            switch ($param['keywords']) {
                case "order_sn":
                    $query->whereLike('order_sn|supplier_sn', "%$param[search]%");
                    break;
                case "merchant":
                    $mid = Merchant::whereLike('name', "%$param[search]%")->column("id");
                    $sid = StationBasic::whereIn('mer_id', $mid)->column("id");
                    $query->whereIn('station_id', $sid);
                    break;
                case "station":
                    $station_id = StationBasic::whereLike('name', "%$param[search]%")->column("id");
                    $query->whereIn('station_id', $station_id);
                    break;
                case "mobile":
                    $mobile = User::whereLike('mobile', "%$param[search]%")->column("id");
                    $query->whereIn('user_id', $mobile);
                    break;
            }
        })->order('create_time', 'desc')->paginate([
            'list_rows' => $param['size'] ?? 30,
            'page' => $param['page'] ?? 1
        ])->toArray();
        $data['data'] = array_map(function ($item) {
            $item['gun_price'] = floatval($item['gun_price']);
            if ($item['gun_discount'] && $item['gun_discount'] != 0) $item['gun_price'] .= "-" . floatval($item['gun_discount']) . $item['gun_unit'];
            if ($item['supplier_discount'] && $item['supplier_discount'] != 0) $item['gun_price'] .= "-" . ((float)($item['supplier_discount'])) . "%";
            return $item;
        }, $data['data']);
        return pageData($data);
    }

    public function download(): array
    {
        $data = $this->lst();
        $station = request()->station ?? [];
//        dd($station);
        $state = [
            0 => '待付款',
            1 => '已付款',
            2 => '已完成',
            3 => '申请退款',
            4 => '退款中',
            5 => '已退款',
            6 => '已取消',
        ];
        $result = array_map(function ($item) use ($state, $station) {
//            dd($station);
            return empty($station) ? [
                $item['order_sn'],
                $item['supplier_sn'],
                $item['station']['name'],
                $item['supplier'] > 0 ? $item['supplierInfo']['name'] : '自有平台',
                $item['litter'],
                $item['gun_price'],
                $item['oil'],
                $item['gun'],
                $item['amount'],
                $item['money'],
                $item['supplier_money'],
                $item['merchant_money'],
                $state[$item['state']] ?? '待付款',
                $item['create_time'],
                $item['payment_time']
            ] : [
                $item['order_sn'],
                $item['supplier_sn'],
                $item['station']['name'],
                $item['supplier'] > 0 ? $item['supplierInfo']['name'] : '自有平台',
                $item['litter'],
                $item['gun_price'],
                $item['oil'],
                $item['gun'],
                $item['amount'],
                $item['merchant_money'],
                $state[$item['state']] ?? '待付款',
                $item['create_time'],
                $item['payment_time']
            ];
        }, $data['list']);
        $header = empty($station) ? [
            '订单号',
            '渠道单号',
            '油站名称',
            '渠道名称',
            '加油数量',
            '油枪单价',
            '油品',
            '油枪',
            '订单金额',
            '实付金额',
            '渠道结算价',
            '商家结算价',
            '状态',
            '下单时间',
            '支付时间'
        ] : [
            '订单号',
            '渠道单号',
            '油站名称',
            '渠道名称',
            '加油数量',
            '油枪单价',
            '油品',
            '油枪',
            '订单金额',
            '结算价',
            '状态',
            '下单时间',
            '支付时间'
        ];
        $file = "油站订单";
        $last_page = $data['last_page'];
        return excelData(compact("result", "header", "file", "last_page"));
    }

    public function cancel()
    {
        $param = request()->post();
        $order = $this->with(['station'])->find($param['id']);
        if ($order['state'] != 0) throw new \Exception("订单状态异常");
        $order->state = 6;
        $order->cancecl_time = date("Y-m-d H:i:s");
        $order->save();
        $station = $order['station'];
        if ($station['mer_id'] > 0) {
            app(Merchant::class)->where('id', $station['mer_id'])->inc('balance', $order['merchant_money'])->dec('disable_balance', $order['merchant_money'])->save();
        }
        return $order;
    }

    public function review()
    {
        $param = request()->post();
        $order = $this->with(['station'])->find($param['id']);
        if ($order['state'] != 3) throw new \Exception("订单状态异常");
        if ($param['state'] == 2) {
            $order->state = 5;
            $order->refund_state = 2;
            $order->cancel_time = date("Y-m-d H:i:s");
            $order->save();
            //同意退单
            if ($order['supplier'] > 0) {
                //推送退单信息给供应商，用户余额加款
                $supplier = app(Supplier::class)->where('id', $order['supplier'])->find();
                if (!empty($supplier)) {
                    if ($supplier['type'] != 3)
                        $supplier->inc($supplier['type'] == 1 ? 'balance' : 'forzen', $order['supplier_money'])->save();
                    //推送给渠道
                    if (!empty($supplier['refund_url'])) {
                        push_notice($supplier['refund_url'], [
                            "refund_state" => 1,
                            "refund_time" => date("Y-m-d H:i:s"),
                            "out_order_sn" => $order['order_sn']
                        ]);
                    }
                }
            } else {
                //给用户退款
                app(SPay::class)->refund($order['money'], $order['order_sn'], $order['refund_sn'], $order['refund_remark'], "https://t");
            }
            //查看是否有商家
            if ($order['station']['mer_id'] > 0) {
                $station = $order['station'];
                $merchant = app(Merchant::class)->where('id', $station['mer_id'])->find();
                //填写动账记录
                app(MerchantBalance::class)->save([
                    "mer_id" => $station['mer_id'],
                    "order_sn" => $order['order_sn'],
                    "content" => $station['name'] . "油站加油退单",
                    "money" => $order['merchant_money'],
                    "old_money" => $merchant['balance'],
                    "new_money" => bcadd(bcadd($merchant['balance'], $merchant['disable_balance'], 2), $order['merchant_money'], 2),
                    "type" => 1,
                    "des" => 3
                ]);
                $merchant->inc("balance", $order['merchant_money'])->save();
            }
        } elseif ($param['state'] == 3) {
            $order->state = 1;
            $order->refund_state = 3;
            $order->refund_apply_text = $param['refund_apply_text'];
            $order->save();
            if ($order['supplier'] > 0) {
                //推送退单信息给供应商
                $supplier = app(Supplier::class)->where('id', $order['supplier'])->find();
                if (!empty($supplier) && $supplier['refund_url']) {
                    //推送给渠道
                    if (!empty($supplier['refund_url'])) {
                        push_notice($supplier['refund_url'], [
                            "refund_state" => 2,
                            "refund_time" => date("Y-m-d H:i:s"),
                            "out_order_sn" => $order['order_sn'],
                            "remark" => $param['refund_apply_text']
                        ]);
                    }
                }
            }
        } elseif ($param['state'] == 4) {
            $order->state = 4;
            $order->save();
//            $station = app(StationBasic::class)->find($order['station_id']);
        }
        return $order;
    }

    public function refund()
    {
        $id = request()->post("id");
        $order = $this->find($id);
        if ($order['state'] != 1) throw new \Exception("订单状态异常");
        $order->state = 3;
        $order->refund_state = 1;
        $order->refund_remark = request()->post("refund_remark");
        $order->refund_sn = setOrderSn("R");
        $order->save();
        return $order;
    }
}
